package com.lzw.tool.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 *
 * @param <T> 实体类
 * @param <R> 父子关系判断字段类型
 */
public class TreeDateUtil<T, R> {

    private Function<T, R> functionParent;

    private Function<T, R> functionChildren;

    private Predicate<T> isRoot;

    /**
     * 默认Parent字段为 <b>null</b> 是根节点
     * @param functionParent 父节点id字段
     * @param functionChildren 当前节点id字段
     */
    public TreeDateUtil(Function<T, R> functionParent, Function<T, R> functionChildren) {
        this.functionParent = functionParent;
        this.functionChildren = functionChildren;
        isRoot = t -> functionParent.apply(t) == null;
    }

    /**
     *
     * @param functionParent 父节点id字段
     * @param functionChildren 当前节点id字段
     * @param isRoot 判断是否根节点
     */
    public TreeDateUtil(Function<T, R> functionParent, Function<T, R> functionChildren, Predicate<T> isRoot) {
        this.functionParent = functionParent;
        this.functionChildren = functionChildren;
        this.isRoot = isRoot;
    }

    /**
     * 建立树形结构
     *
     * @param resourceRespList 对象列表
     * @return 树形结构
     */
    public List<ResourceTree<T>> buildTree(List<T> resourceRespList) {
        List<ResourceTree<T>> rootNodes = getRootNode(resourceRespList);
        for (ResourceTree<T> node : rootNodes) {
            buildChildrenTree(node, resourceRespList);
        }
        return rootNodes;
    }

    /**
     * 获取根节点
     *
     * @param resourceRespList 对象列表
     * @return 根节点
     */
    @Deprecated
    public List<ResourceTree<T>> getRootNodeOld(List<T> resourceRespList) {
        List<ResourceTree<T>> rootNodeList = new ArrayList<>();
        ResourceTree<T> temp;
        final Iterator<T> iterator = resourceRespList.iterator();
        T next;
        while (iterator.hasNext()) {
            next = iterator.next();
            if (functionParent.apply(next) == null) {
                temp = new ResourceTree<>(next);
                rootNodeList.add(temp);
                iterator.remove();
            }
        }
        return rootNodeList;
    }

    public List<ResourceTree<T>> getRootNode(List<T> resourceRespList) {
        return getRootNode(resourceRespList, this.isRoot);
    }

    /**
     * @param resourceRespList 对象列表
     * @param isRoot        主节点判断
     * @return 根节点
     */
    public List<ResourceTree<T>> getRootNode(List<T> resourceRespList, Predicate<T> isRoot) {
        List<ResourceTree<T>> rootNodeList = new ArrayList<>();
        ResourceTree<T> temp;
        final Iterator<T> iterator = resourceRespList.iterator();
        T next;
        while (iterator.hasNext()) {
            next = iterator.next();
            //判断是否主节点
            if (isRoot.test(next)) {
                temp = new ResourceTree<>(next);
                rootNodeList.add(temp);
                iterator.remove();
            }
        }
        return rootNodeList;
    }

    /**
     * 递归，建立子树形结构
     *
     * @param pNode            父节点
     * @param resourceRespList 所有资源
     */
    private void buildChildrenTree(ResourceTree<T> pNode, List<T> resourceRespList) {
        List<ResourceTree<T>> ChildrenTree = new ArrayList<>();
        final Iterator<T> iterator = resourceRespList.iterator();
        ResourceTree<T> temp;
        T next;
        while (iterator.hasNext()) {
            next = iterator.next();
            if (Objects.equals(functionParent.apply(next), functionChildren.apply(pNode.getData()))) {
                temp = new ResourceTree<>(next, pNode.getLevel() + 1);
                ChildrenTree.add(temp);
                iterator.remove();
            }
        }
        if (!ChildrenTree.isEmpty()) {
            pNode.setChildren(ChildrenTree);
            for (ResourceTree<T> node : ChildrenTree) {
                buildChildrenTree(node, resourceRespList);
            }
        }
    }

}
